package com.ww.springboot.boot.redisson.ratelimiter;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;

public class RedisRateLimiterClient implements RateLimiterClient {
    private static final String REDIS_KEY_PREFIX = "limiter:";
    private static final long FAIL_CODE = 0L;
    private final StringRedisTemplate redisTemplate;
    private final RedisScript<List<Long>> script;
    private final Environment environment;

    public boolean isAllowed(String key, long max, long ttl, TimeUnit timeUnit) {
        String redisKeyBuilder = "limiter:" + getApplicationName(this.environment) + ':' + key;
        List<String> keys = Collections.singletonList(redisKeyBuilder);
        long now = System.currentTimeMillis();
        long ttlMillis = timeUnit.toMillis(ttl);
        List<Long> results = (List) this.redisTemplate.execute(this.script, keys, new Object[]{max + "", ttlMillis + "", now + ""});
        if (results != null && !results.isEmpty()) {
            Long result = (Long) results.get(0);
            return result != 0L;
        } else {
            return false;
        }
    }

    private static String getApplicationName(Environment environment) {
        return environment.getProperty("spring.application.name", "");
    }

    public RedisRateLimiterClient(final StringRedisTemplate redisTemplate, final RedisScript<List<Long>> script, final Environment environment) {
        this.redisTemplate = redisTemplate;
        this.script = script;
        this.environment = environment;
    }
}
